#include "ACTIONHANDLER.H"
#include "MetaXmlHandler.h"
#include "ORACLEADAPTER.h"
#include <list>
#include "comtools.h"

#import "msado15.dll" rename_namespace("ADODB") rename("EOF", "ADOEOF") 

ActionHandler::ActionHandler()
: MetaStorageBase()
{
}

ActionHandler::~ActionHandler()
{
}

void ActionHandler::SelectActionData(const char * pAction, Action ** ppAction)
{
  HRESULT hr = S_FALSE;
  try {
    long lStepCount = 0;
    _bstr_t eventName, eventExec, eventId, seqName, severity, actionName, actionTime, category;
    std::list<Step*> liSteps;

    MetaXmlHandler xmlhnd(pAction);
    actionName = xmlhnd.getNodeValue("//action/name");
    eventExec = xmlhnd.getNodeValue("//events/event/executable");
    eventName = xmlhnd.getNodeValue("//events/event/name");
    category = xmlhnd.getNodeValue("//events/event/category");
    seqName = xmlhnd.getAttrValue("//set/sequence", "name");
    severity = xmlhnd.getAttrValue("//events/event", "severity");
    actionTime = xmlhnd.getNodeValue("//message/header/date");

    (*ppAction) = new Action(eventExec, eventName, seqName, actionName, severity);
    (*ppAction)->setActionTime(actionTime);
    (*ppAction)->setEventCategory(category);

    xmlhnd.getActionSteps(liSteps);
    std::list<Step*>::iterator ite;
    for (ite = liSteps.begin(); ite != liSteps.end(); ++ite) {
      Step * s = new Step(*ite);
      (*ppAction)->addStep(s);
    }
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void ActionHandler::SearchActionMetaData(const char * pEvent, Action ** ppAction)
{
  HRESULT hr = S_FALSE;
  try {
    _bstr_t eventName, eventExec, eventId, seqName, severity, actionTime, category;

    SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
    if (NULL == pAdapt) return;

    MetaXmlHandler xmlhnd(pEvent);
    eventName = xmlhnd.getNodeValue("//event/name");
    eventExec = xmlhnd.getNodeValue("//event/executable");
    category = xmlhnd.getNodeValue("//event/category");
    seqName = xmlhnd.getAttrValue("//set/sequence", "name");
    eventId = xmlhnd.getNodeValue("//header/id");
    severity = xmlhnd.getAttrValue("//event", "severity");

    _bstr_t sql = " select "
                  "         getdate() as msg_date, "
                  "         a.action_name, "
                  "         a.action_step, "
                  "         a.description, "
                  "         isnull(a.command, ' ') as command, "
                  "         isnull(a.parameters, ' ') as parameters "
                  " from "
                  "         action a, event_action ea "
                  " where "
                  "         a.action_name = ea.action_name "
                  "         and ea.event_name = '"+ eventName +"' \n";

    ADODB::_RecordsetPtr rs;  
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  
    if (!rs->ADOEOF) hr = rs->MoveFirst();
    while (S_OK == hr && !rs->ADOEOF) {          
      _bstr_t name = (_bstr_t)rs->Fields->GetItem(L"ACTION_NAME")->GetValue();
      long step = (long)rs->Fields->GetItem(L"ACTION_STEP")->GetValue();
      _bstr_t desc = (_bstr_t)rs->Fields->GetItem(L"DESCRIPTION")->GetValue();
      _bstr_t cmd = (_bstr_t)rs->Fields->GetItem(L"COMMAND")->GetValue();
      _bstr_t param = (_bstr_t)rs->Fields->GetItem(L"PARAMETERS")->GetValue();
      _bstr_t date = _bstr_t(rs->Fields->GetItem(L"MSG_DATE")->GetValue());
     
      if (_bstr_t("") != name) {
        if (NULL == (*ppAction)) {
          (*ppAction) = new Action(eventExec, eventName, seqName, name, severity);
        }
        (*ppAction)->setEventCategory(category);

        Step * pStep = new Step(step, desc, cmd);
        (*ppAction)->addStep(pStep);
        delete pStep;
      }

      hr = rs->MoveNext();
    }
    try { rs->Close(); } catch (...) { }
  } catch (_com_error &e) {
    BSTR b;
    if (e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      ::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
    }
  } catch (...) {

  }
}

void ActionHandler::saveObject(MessageQueueObject * obj)
{

}

std::list<MessageQueueObject*>& ActionHandler::search(const char* pszExec, const char* pszClassName, const char* pszMethodName, std::list<MessageQueueObject*>& list)
{
  return list;
}

void ActionHandler::StoreActionForLog(Action * pAction)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  HRESULT hr;
  ADODB::_RecordsetPtr rs;  
  hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
  hr = rs->Open(L"LOG_EVENT", _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdTable);  

  rs->AddNew();
  rs->Fields->GetItem(L"event_time")->Value = pAction->getActionTime();
  rs->Fields->GetItem(L"application_name")->Value = pAction->getExecutable();
  rs->Fields->GetItem(L"alias")->Value = pAction->getEventCategory();
  rs->Fields->GetItem(L"event_name")->Value = pAction->getEventName();
  rs->Fields->GetItem(L"event_severity")->Value = pAction->getSeverity();
  rs->Fields->GetItem(L"action_name")->Value = pAction->getActionName();
  rs->Update();

  try { rs->Close(); } catch (...) {}
}

long ActionHandler::getLastLogIdForLog()
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return 0;

  long lLastId = 0;
  try {
    HRESULT hr;

    _bstr_t sql = "SELECT ISNULL(MAX(LOG_ID), 0) AS LAST_ID FROM LOG_EVENT";

    ADODB::_RecordsetPtr rs;  
    hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
    hr = rs->Open(sql, _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdText);  

    if (!rs->ADOEOF) hr = rs->MoveFirst();
    if (S_OK == hr && !rs->ADOEOF) {  
      lLastId = (long)rs->Fields->GetItem(L"LAST_ID")->Value;
    }
    try { rs->Close(); } catch (...) {}
  } catch (_com_error &e) {
    BSTR b;
    if (NULL != e.ErrorInfo()) {
      e.ErrorInfo()->GetDescription(&b);
      char szErr[256];
      sprintf(szErr, "Error: %s\n",_com_util::ConvertBSTRToString(b));
      //::MessageBox(NULL, szErr, "Message Queue Error", MB_ICONERROR | MB_OK);
      OutputDebugString(szErr);
    }
  }
  return lLastId;
}

void ActionHandler::StoreActionProcedureForLog(long lLastLogId, const char* pszActionName, std::list<Step*>& liProcedure)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  HRESULT hr;
  ADODB::_RecordsetPtr rs;  
  hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
  hr = rs->Open(L"LOG_PROCEDURE", _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdTable);  

  std::list<Step*>::const_iterator ite;
  for (ite = liProcedure.begin(); ite != liProcedure.end(); ++ite) {
    rs->AddNew();
    rs->Fields->GetItem(L"log_id")->Value = lLastLogId;
    rs->Fields->GetItem(L"action_name")->Value = pszActionName;
    rs->Fields->GetItem(L"step")->Value = (*ite)->getStepNo();
    rs->Fields->GetItem(L"description")->Value = (*ite)->getDescription();
    rs->Fields->GetItem(L"command")->Value = (*ite)->getCommand();
    rs->Fields->GetItem(L"status")->Value = 0;
    rs->Update();
  }
  try { rs->Close(); } catch (...) {}
}

void ActionHandler::StoreActionTraceForLog(long lLastLogId, const char* pszActionName, std::list<Trace*>& liTraces)
{
  SQLServerAdapter * pAdapt = dynamic_cast<SQLServerAdapter*>(m_pDb);
  if (NULL == pAdapt) return;

  HRESULT hr;
  ADODB::_RecordsetPtr rs;  
  hr = rs.CreateInstance (__uuidof(ADODB::Recordset));  
  hr = rs->Open(L"LOG_TRACE", _variant_t(pAdapt->getConnecion(),false), ADODB::adOpenDynamic, ADODB::adLockOptimistic, ADODB::adCmdTable);  

  std::list<Trace*>::const_iterator ite;
  for (ite = liTraces.begin(); ite != liTraces.end(); ++ite) {
    rs->AddNew();
    rs->Fields->GetItem(L"log_id")->Value = lLastLogId;
    rs->Fields->GetItem(L"action_name")->Value = pszActionName;
    rs->Fields->GetItem(L"class_name")->Value = (*ite)->getClass();
    rs->Fields->GetItem(L"method_name")->Value = (*ite)->getMethod();
    rs->Fields->GetItem(L"direction")->Value = (*ite)->getDirection();
    rs->Update();
  }
  try { rs->Close(); } catch (...) {}
}
